home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Technology Seed / Jan. '98 ATS.toast / NavServices1.0b3 / Navigation Services SDK / Examples / Sampler / Sampler ƒ / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-12  |  22.7 KB  |  886 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        file.c
  3.  
  4.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  5.  
  6. */
  7.  
  8. #pragma segment DocSeg
  9.  
  10. #ifndef __STRINGS__
  11. #include <Strings.h>
  12. #endif
  13.  
  14. #ifndef __STDIO__
  15. #include <StdIO.h>
  16. #endif
  17.  
  18. #ifndef __STANDARDFILE__
  19. #include <StandardFile.h>
  20. #endif
  21.  
  22. #ifndef __FINDER__
  23. #include <Finder.h>
  24. #endif
  25.  
  26. #ifndef __SOUND__
  27. #include <Sound.h>
  28. #endif
  29.  
  30. #ifndef __NAVIGATION__
  31. #include "Navigation.h"
  32. #endif
  33.  
  34.  
  35. #ifndef Common_Defs
  36. #include "Common.h"
  37. #endif
  38.  
  39. const long kPictHeaderSize = 512;
  40.  
  41. short ReadFile(Document* theDocument);
  42. short WriteFile(Document* theDocument);
  43. short WriteNewFile(Document* theDocument, FSSpec* newFileSpec);
  44. short DoSaveAsDocument(Document* theDocument);
  45. short DoSaveAsDocumentOldWay(Document* theDocument);
  46.  
  47. pascal Boolean myFilterProc(AEDesc* theItem, void* info, NavCallBackUserData callBackUD, NavFilterModes filterMode);
  48.  
  49. extern Document* gDocumentList[kMaxDocumentCount];
  50. extern Boolean gNavServicesExists;
  51.  
  52.  
  53. // *****************************************************************************
  54. // *
  55. // *    ReadFile()
  56. // *
  57. // *****************************************************************************
  58. short ReadFile(Document* theDocument)
  59. {    
  60.     long        count;
  61.     short        theResult;
  62.     char        buffer[256];
  63.     TextStyle    theStyle;
  64.  
  65.     SetCursor(*GetCursor(watchCursor));
  66.  
  67.     if (theDocument->theTE != NULL)
  68.         {
  69.         TESetSelect(0,(**(theDocument->theTE)).teLength,theDocument->theTE);
  70.         TEDelete(theDocument->theTE);
  71.  
  72.         if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  73.             return theResult;
  74.  
  75.         do    {
  76.             count = 256;
  77.             theResult = FSRead(theDocument->fRefNum,&count,&buffer);
  78.             TEInsert(&buffer,count,theDocument->theTE);
  79.             }
  80.         while (theResult == noErr);
  81.  
  82.         if (theResult == eofErr)
  83.             theResult = noErr;
  84.     
  85.         TESetSelect(0,32767,theDocument->theTE);
  86.         theStyle.tsFont = 21;
  87.         theStyle.tsSize = 12;
  88.         TESetStyle(doFont + doSize,&theStyle,true,theDocument->theTE);
  89.         TESetSelect(0,0,theDocument->theTE);
  90.         }
  91.     else
  92.         {
  93.         short     result = noErr;
  94.         long    fileSize = 0;
  95.         long    headerSize = 0;
  96.         long    pictSize = 0;
  97.  
  98.         SetCursor(*(Cursor**)GetCursor(watchCursor));
  99.         
  100.         if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  101.             return theResult;
  102.  
  103.         theResult = GetEOF(theDocument->fRefNum,&fileSize);
  104.         
  105.         theDocument->fPictLength = fileSize;
  106.         theDocument->fPictLength -= kPictHeaderSize;
  107.         theDocument->fPict = NewHandle(theDocument->fPictLength);
  108.         theDocument->fHeader = NewHandle(kPictHeaderSize);
  109.         if ((theDocument->fPict == NULL)||(theDocument->fPict == NULL))
  110.             {
  111.             SysBeep(5);
  112.             return memFullErr;
  113.             }
  114.         headerSize = kPictHeaderSize;
  115.         pictSize = theDocument->fPictLength;
  116.  
  117.         theResult = FSRead(theDocument->fRefNum,&headerSize,*theDocument->fHeader);
  118.         theResult = FSRead(theDocument->fRefNum,&pictSize,*theDocument->fPict);
  119.         }
  120.  
  121.     theDocument->dirty = false;
  122.  
  123.     if (theResult != noErr)
  124.         {
  125.         Str255 errorStr;
  126.         GetIndString(errorStr,rAppStringsID,sReadErr);
  127.         ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  128.         NoteAlert(rGenericAlertID,0L);
  129.         }
  130.     return theResult;
  131. }
  132.  
  133.  
  134. // *****************************************************************************
  135. // *
  136. // *    WriteFile()
  137. // *
  138. // *****************************************************************************
  139. short WriteFile(Document* theDocument)
  140. {    
  141.     short    theResult;
  142.     long    length;
  143.     char*    bufPtr;
  144.  
  145.     SetCursor(*GetCursor(watchCursor));
  146.  
  147.     if (!theDocument->fRefNum)
  148.         return fnOpnErr;
  149.  
  150.     if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  151.         return theResult;
  152.  
  153.     if (theDocument->theTE != NULL)
  154.         {
  155.         length = (**(theDocument->theTE)).teLength;
  156.         bufPtr = *((**(theDocument->theTE)).hText);
  157.  
  158.         theResult = FSWrite(theDocument->fRefNum,&length,bufPtr);
  159.         if (theResult == noErr)
  160.             theResult = SetEOF(theDocument->fRefNum,length);
  161.         }
  162.     else
  163.         {
  164.         long headerSize = kPictHeaderSize;
  165.         long pictSize = theDocument->fPictLength;
  166.  
  167.         theResult = FSWrite(theDocument->fRefNum,&headerSize,*theDocument->fHeader);
  168.         if (theResult == noErr)
  169.             {
  170.             theResult = FSWrite(theDocument->fRefNum,&pictSize,*theDocument->fPict);    
  171.             if (theResult == noErr)
  172.                 theResult = SetEOF(theDocument->fRefNum,headerSize+pictSize);
  173.             }
  174.         }
  175.  
  176.     return theResult;
  177. }
  178.  
  179.  
  180. // *****************************************************************************
  181. // *
  182. // *    WriteNewFile()
  183. // *
  184. // *****************************************************************************
  185. short WriteNewFile(Document* theDocument, FSSpec* newFileSpec)
  186. {    
  187.     short    theResult;
  188.     short    refNum = 0;
  189.  
  190.     SetCursor(*GetCursor(watchCursor));
  191.  
  192.     theResult = FSpOpenDF(newFileSpec,fsRdWrPerm,&refNum);
  193.     if (refNum != -1)
  194.         {
  195.         if (theResult = SetFPos(refNum,fsFromStart,0))
  196.             return(theResult);
  197.  
  198.         if (theDocument->theTE != NULL)
  199.             {
  200.             long    length;
  201.             char*    bufPtr;
  202.             length = (**(theDocument->theTE)).teLength;
  203.             bufPtr = *((**(theDocument->theTE)).hText);
  204.  
  205.             if (theResult = FSWrite(refNum,&length,bufPtr))
  206.                 return(theResult);
  207.  
  208.             theResult = SetEOF(refNum,length);
  209.             }
  210.         else
  211.             {
  212.             long headerSize = kPictHeaderSize;
  213.             long pictSize = theDocument->fPictLength;
  214.  
  215.             theResult = FSWrite(refNum,&headerSize,*theDocument->fHeader);
  216.             theResult = FSWrite(refNum,&pictSize,*theDocument->fPict);
  217.             
  218.             theResult = SetEOF(refNum,headerSize+pictSize);
  219.             }
  220.         theResult = FSClose(refNum);
  221.         }
  222.     return theResult;
  223. }
  224.  
  225.  
  226. // *****************************************************************************
  227. // *
  228. // *    DoNewDocument()
  229. // *
  230. // *****************************************************************************
  231. void DoNewDocument(Boolean newDocAsPICT)
  232. {    
  233.     Document* theDocument;
  234.     if (theDocument = NewDocument(newDocAsPICT))
  235.         ShowWindow(theDocument->theWindow);
  236. }
  237.  
  238.  
  239. // *****************************************************************************
  240. // *
  241. // *    DoOpenFile()
  242. // *
  243. // *****************************************************************************
  244. OSErr DoOpenFile(FSSpec* theFile, Boolean openAsPICT)
  245. {    
  246.     OSErr        result;
  247.     short        refNum;
  248.     Document*    theDocument = NULL;
  249.  
  250.     result = FSpOpenDF(theFile,fsRdWrPerm,&refNum);
  251.     if ((result == fLckdErr) || (result == afpAccessDenied))
  252.         result = FSpOpenDF(theFile,fsRdPerm,&refNum);
  253.  
  254.     if (result == noErr)
  255.         {
  256.         theDocument = NewDocument(openAsPICT);
  257.         if (theDocument != NULL)
  258.             {
  259.             theDocument->fRefNum = refNum;
  260.             
  261.             result = ReadFile(theDocument);
  262.                 
  263.             SetWTitle(theDocument->theWindow,theFile->name);
  264.             SizeDocWindow(theDocument);
  265.  
  266.             AdjustScrollBar(theDocument);
  267.             ShowWindow(theDocument->theWindow);    
  268.             }
  269.         else
  270.             {
  271.             FSClose(refNum);
  272.             result = memFullErr;
  273.             }
  274.         }
  275.     else
  276.         {
  277.         Str255 errorStr;
  278.         if (result == vLckdErr || result == afpVolLocked || result == wPrErr || result == permErr)
  279.             GetIndString(errorStr,rAppStringsID,sWriteToBusyFileErr);
  280.         else
  281.             if (result == opWrErr)
  282.                 GetIndString(errorStr,rAppStringsID,sBusyOpen);
  283.             else
  284.                 GetIndString(errorStr,rAppStringsID,sOpeningErr);
  285.         ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  286.         NoteAlert(rGenericAlertID,0L);
  287.         }
  288.     return result;
  289. }
  290.  
  291.  
  292. // *****************************************************************************
  293. // *
  294. // *    myFilterProc()
  295. // *
  296. // *****************************************************************************
  297. pascal Boolean myFilterProc(AEDesc* theItem, void* info, NavCallBackUserData /*callBackUD*/, NavFilterModes /*filterMode*/)
  298. {
  299.     OSErr theErr = noErr;
  300.     Boolean display = true;
  301.     NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info;
  302.     
  303.     if ( theItem->descriptorType == typeFSS )
  304.         if ( !theInfo->isFolder )
  305.             {
  306.             // use:
  307.             // 'theInfo->fileAndFolder.fileInfo.finderInfo.fdType'
  308.             // to check for the file type you want to filter.
  309.             }
  310.     return display;
  311. }
  312.  
  313.  
  314. // *****************************************************************************
  315. // *
  316. // *    myEventProc()    
  317. // *
  318. // *****************************************************************************
  319. pascal void myEventProc(const NavEventCallbackMessage callBackSelector, 
  320.                         NavCBRecPtr callBackParms, 
  321.                         NavCallBackUserData callBackUD)
  322. {
  323.     WindowPtr    pWindow = NULL;
  324.     Document**    docList;
  325.     Document*    theDoc = NULL;
  326.     short         index = 0;
  327.  
  328.     if (callBackUD != 0)
  329.         switch (callBackSelector)
  330.             {
  331.             case kNavCBEvent:
  332.                 {
  333.                 docList = (Document**)callBackUD;
  334.                 if (docList != NULL)
  335.                     switch (callBackParms->eventData.event->what)
  336.                         {
  337.                         case nullEvent:
  338.                             break;
  339.                             
  340.                         case updateEvt:
  341.                             pWindow = (WindowPtr)callBackParms->eventData.event->message;
  342.                             theDoc = docList[index];
  343.                             if (theDoc != NULL)
  344.                                 {
  345.                                 while ((theDoc->theWindow != pWindow) && (docList[index] != NULL))
  346.                                     {
  347.                                     index++;
  348.                                     theDoc = docList[index];
  349.                                     }
  350.                                 theDoc = docList[index];
  351.                                 if (theDoc != NULL)
  352.                                     UpdateWindow(theDoc);
  353.                                 }
  354.                             break;
  355.  
  356.                         case activateEvt:
  357.                             break;
  358.  
  359.                         default:
  360.                             break;
  361.                         }
  362.                 break;
  363.                 }
  364.             }
  365. }
  366.  
  367.  
  368. // *****************************************************************************
  369. // *
  370. // *    DoOpenDocumentTheOldWay()
  371. // *
  372. // *****************************************************************************
  373. OSErr DoOpenDocumentTheOldWay()
  374. {    
  375.     OSErr theErr = noErr;
  376.     SFTypeList            theTypeList;
  377.     StandardFileReply    theReply;
  378.  
  379.     theTypeList[0] = 'TEXT';
  380.     theTypeList[1] = 'PICT';
  381.     StandardGetFile(0L,2,theTypeList,&theReply);
  382.  
  383.     if (theReply.sfGood)
  384.         {
  385.         if (theReply.sfType == 'TEXT')
  386.             DoOpenFile(&theReply.sfFile,false);
  387.         else
  388.             DoOpenFile(&theReply.sfFile,true);
  389.         }
  390.     return theErr;
  391. }
  392.  
  393.  
  394. // *****************************************************************************
  395. // *
  396. // *    DoOpenDocument()
  397. // *
  398. // *****************************************************************************
  399. OSErr DoOpenDocument()
  400. {    
  401.     NavReplyRecord        theReply;
  402.     NavDialogOptions    dialogOptions;
  403.     OSErr                theErr = noErr;
  404.     NavTypeListHandle    openList = NULL;
  405.     long                count = 0;
  406.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  407.     NavObjectFilterUPP    filterUPP = NewNavObjectFilterProc(myFilterProc);
  408.     
  409.     // default behavior for browser and dialog:
  410.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  411.  
  412.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  413.     
  414.     openList = (NavTypeListHandle)GetResource(kOpenRsrcType,kOpenRsrcID);
  415.  
  416.     dialogOptions.preferenceKey = kOpenPrefKey;
  417.  
  418.     dialogOptions.dialogOptionFlags += kNavDontAutoTranslate;    // we will do the translation ourselves later:
  419.  
  420.     theErr = NavGetFile(NULL,    // use system's default location
  421.                         &theReply,
  422.                         &dialogOptions,
  423.                         eventUPP,
  424.                         NULL,    // no custom previews
  425.                         filterUPP,
  426.                         (NavTypeListHandle)openList,
  427.                         (NavCallBackUserData)&gDocumentList);
  428.  
  429.     DisposeRoutineDescriptor(eventUPP);
  430.     DisposeRoutineDescriptor(filterUPP);
  431.  
  432.     if (theReply.validRecord && theErr == noErr)
  433.         {
  434.         // since we allow for multiple objects to be returned,
  435.         // grab the target FSSpecs from 'theReply.fileRef' list for opening:    
  436.         FSSpec    finalFSSpec;    
  437.         AEDesc     resultDesc;
  438.         FInfo    fileInfo;
  439.  
  440.         // in the case we didn't want built in translation:
  441.         if ((dialogOptions.dialogOptionFlags & kNavDontAutoTranslate) != 0)
  442.             if (theReply.translationNeeded)
  443.                 {
  444.                 // if we didn't want built in translation it was for the following reasons:
  445.                 //        1) we wanted to do it ourselves
  446.                 //        2) or we wanted to defer it    
  447.                 // things to remember if auto-translation is turned off:
  448.                 //         1) the AEDesc list contains the original file specs the user had chosen.
  449.                 //        2) the 'fileTranslation' field for each object that needs translation has filled in for you.
  450.                 
  451.                 // put your own code here to perform your own translation.
  452.                 // - or -
  453.                 // we can simply call this to perform the translation manually:
  454.                 Str255     errorStr;
  455.  
  456.                 if ((theErr = NavTranslateFile(&theReply,kNavTranslateCopy)) != noErr)
  457.                     {
  458.                     if (theErr == vLckdErr || theErr == afpVolLocked || theErr == wPrErr || theErr == permErr)
  459.                         GetIndString(errorStr,rAppStringsID,sTranslationLockedErr);
  460.                     else
  461.                         GetIndString(errorStr,rAppStringsID,sTranslationErr);
  462.                     ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  463.                     NoteAlert(rGenericAlertID,0L);
  464.                     }
  465.                 }
  466.  
  467.         if (theErr == noErr)
  468.             {
  469.             // we are ready to open the document(s), grab information about each file for opening:
  470.             theErr = AECountItems(&(theReply.selection),&count);
  471.             for (long index=1;index<=count;index++)
  472.                 {
  473.                 resultDesc.dataHandle = 0L;
  474.                 theErr = AEGetNthDesc(&(theReply.selection),index,typeFSS,NULL,&resultDesc);
  475.                 if (theErr == noErr)
  476.                     {
  477.                     BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  478.                 
  479.                     // decide if the doc we are opening is a 'PICT' or 'TEXT':
  480.                     theErr = FSpGetFInfo(&finalFSSpec,&fileInfo);
  481.                     if (theErr == noErr)
  482.                         {
  483.                         if (fileInfo.fdType == kFileType)
  484.                             (void)DoOpenFile(&finalFSSpec,false);
  485.                         else
  486.                             if (fileInfo.fdType == kFileTypePICT)
  487.                                 (void)DoOpenFile(&finalFSSpec,true);
  488.                             else
  489.                                 {
  490.                                 // error:
  491.                                 // if we got this far, the document is a type we can't open and
  492.                                 // (most likely) built-in translation was turned off.
  493.                                 // You can alert the user that this returned selection or file spec
  494.                                 // needs translation.
  495.                                 }
  496.                         }
  497.                     theErr = AEDisposeDesc(&resultDesc);
  498.                     }
  499.                 }
  500.             }
  501.         
  502.         theErr = NavDisposeReply(&theReply);    // clean up after ourselves    
  503.         }
  504.  
  505.     if (openList != NULL)
  506.         ReleaseResource((Handle)openList);
  507.  
  508.     return theErr;
  509. }
  510.  
  511.  
  512. // *****************************************************************************
  513. // *
  514. // *    SaveACopyDocumentTheOldWay()
  515. // *
  516. // *****************************************************************************
  517. OSErr SaveACopyDocumentTheOldWay(Document* theDocument)
  518. {
  519.     OSErr                theErr = noErr;
  520.     Str255                thePrompt, theName;
  521.     StandardFileReply    theReply;
  522.  
  523.     if (!theDocument)
  524.         return false;
  525.  
  526.     GetIndString((unsigned char*)&thePrompt,rAppStringsID,sSaveCopyMessage);
  527.     GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  528.     StandardPutFile((unsigned char*)&thePrompt,(unsigned char*)&theName,&theReply);
  529.  
  530.     if (theReply.sfGood)
  531.         {
  532.         if (theReply.sfReplacing)
  533.             theErr = FSpDelete(&theReply.sfFile);
  534.  
  535.         if ((theErr = FSpCreate(&theReply.sfFile,kFileCreator,'TEXT',smSystemScript)) == noErr)
  536.             theErr = WriteNewFile(theDocument,&theReply.sfFile);    // use this document's data to write to our new copy:
  537.         
  538.         if (theErr == fBsyErr)
  539.             {
  540.             Str255 errorStr;
  541.             GetIndString(errorStr,rAppStringsID,sWriteToBusyFileErr);
  542.             ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  543.             NoteAlert(rGenericAlertID,0L);
  544.             }
  545.         }
  546.     else
  547.         return false;
  548.         
  549.     return true;
  550. }
  551.  
  552.  
  553. // *****************************************************************************
  554. // *
  555. // *    SaveACopyDocument()
  556. // *
  557. // *****************************************************************************
  558. OSErr SaveACopyDocument(Document* theDocument)
  559. {    
  560.     OSErr                theErr = noErr;
  561.     NavReplyRecord        theReply;
  562.     NavDialogOptions    dialogOptions;
  563.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  564.     Str255                docTitle;
  565.     OSType                fileTypeToSave;
  566.  
  567.     // default behavior for browser and dialog:
  568.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  569.  
  570.     // user might want to translate the saveed doc into another format
  571.     dialogOptions.dialogOptionFlags -= kNavDontAddTranslateItems;
  572.  
  573.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  574.  
  575.     GetWTitle(theDocument->theWindow,docTitle);
  576.     p2cstr((StringPtr)docTitle);
  577.     sprintf((char*)dialogOptions.savedFileName,(char*)"%s copy",docTitle);
  578.     c2pstr((Ptr)dialogOptions.savedFileName);
  579.         
  580.     if (theDocument->theTE != NULL)    // which document type is it?
  581.         fileTypeToSave = kFileType;
  582.     else
  583.         fileTypeToSave = kFileTypePICT;
  584.  
  585.     dialogOptions.preferenceKey = kSavePrefKey;
  586.  
  587.     theErr = NavPutFile(NULL,    // use system's default location
  588.                         &theReply,
  589.                         &dialogOptions,
  590.                         eventUPP,
  591.                         fileTypeToSave,
  592.                         kFileCreator,
  593.                         (NavCallBackUserData)&gDocumentList);
  594.  
  595.     DisposeRoutineDescriptor(eventUPP);
  596.  
  597.     if (theReply.validRecord && theErr == noErr)
  598.         {
  599.         FSSpec    finalFSSpec;    
  600.         AEDesc     resultDesc;    
  601.         resultDesc.dataHandle = 0L;
  602.         
  603.         // retrieve the returned selection:
  604.         // since only 1 selection is possible, we get the first AEDesc:
  605.         theErr = AEGetNthDesc(&(theReply.selection),1,typeFSS,NULL,&resultDesc);
  606.         if (theErr == noErr)
  607.             {
  608.             BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  609.  
  610.             if (theReply.replacing)
  611.                 theErr = FSpDelete(&finalFSSpec);
  612.             if (theErr == noErr)
  613.                 {
  614.                 theErr = FSpCreate(&finalFSSpec,kFileCreator,fileTypeToSave,smSystemScript);
  615.                 if (theErr == noErr)
  616.                     {
  617.                     theErr = WriteNewFile(theDocument,&finalFSSpec);    // use this document's data to write to our new copy
  618.                     if (theErr == noErr)
  619.                         {
  620.                         // translation may be needed for file we are saving a copy of,
  621.                         // when you save a copy, you should always "translate in place":
  622.                         theErr = NavCompleteSave(&theReply,kNavTranslateInPlace);
  623.                         }
  624.                     }
  625.                 }
  626.             else
  627.                 if (theErr == fBsyErr)
  628.                     {
  629.                     Str255 errorStr;
  630.                     GetIndString(errorStr,rAppStringsID,sReadErr);
  631.                     ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  632.                     NoteAlert(rGenericAlertID,0L);
  633.                     }
  634.             }
  635.         theErr = NavDisposeReply(&theReply);
  636.         }
  637.     
  638.     return theErr;
  639. }
  640.  
  641.  
  642. // *****************************************************************************
  643. // *
  644. // *    DoSaveAsDocument()
  645. // *
  646. // *****************************************************************************
  647. short DoSaveAsDocument(Document* theDocument)
  648. {
  649.     OSErr                theErr = noErr;
  650.     short                result = true;
  651.     NavReplyRecord        theReply;
  652.     NavDialogOptions    dialogOptions;
  653.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  654.     OSType                fileTypeToSave;
  655.  
  656.     // default behavior for browser and dialog:
  657.     NavGetDefaultDialogOptions(&dialogOptions);
  658.  
  659.     // user might want to translate the saveed doc into another format
  660.     dialogOptions.dialogOptionFlags -= kNavDontAddTranslateItems;
  661.  
  662.     GetWTitle(theDocument->theWindow,dialogOptions.savedFileName);
  663.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  664.             
  665.     if (theDocument->theTE != NULL)    // which document type is it?
  666.         fileTypeToSave = kFileType;
  667.     else
  668.         fileTypeToSave = kFileTypePICT;
  669.  
  670.     dialogOptions.preferenceKey = kSavePrefKey;
  671.  
  672.     theErr = NavPutFile(NULL,    // use system's default location
  673.                         &theReply,
  674.                         &dialogOptions,
  675.                         eventUPP,
  676.                         fileTypeToSave,
  677.                         kFileCreator,
  678.                         (NavCallBackUserData)&gDocumentList);
  679.     DisposeRoutineDescriptor(eventUPP);
  680.  
  681.     if (theReply.validRecord && theErr == noErr)
  682.         {
  683.         FSSpec    finalFSSpec;    
  684.         AEDesc     resultDesc;    
  685.         resultDesc.dataHandle = 0L;
  686.         
  687.         // retrieve the returned selection:
  688.         theErr = AEGetNthDesc(&(theReply.selection),1,typeFSS,NULL,&resultDesc);
  689.         if (theErr == noErr)
  690.             {
  691.             BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  692.  
  693.             if (!theReply.replacing)
  694.                 {
  695.                 result = FSpCreate(&finalFSSpec,kFileCreator,fileTypeToSave,theReply.keyScript);
  696.                 if (result)
  697.                     {
  698.                     SysBeep(5);
  699.                     return false;
  700.                     }
  701.                 }
  702.                 
  703.             if (theDocument->fRefNum)
  704.                 result = FSClose(theDocument->fRefNum);
  705.             
  706.             result = FSpOpenDF(&finalFSSpec,fsRdWrPerm,&theDocument->fRefNum);
  707.             if (result)
  708.                 {
  709.                 SysBeep(5);
  710.                 return false;
  711.                 }
  712.  
  713.             if (result = WriteFile(theDocument))
  714.                 return false;
  715.  
  716.             theErr = NavCompleteSave(&theReply,kNavTranslateInPlace);
  717.  
  718.             SetWTitle(theDocument->theWindow,(unsigned char*)finalFSSpec.name);
  719.             theDocument->dirty = false;
  720.             }
  721.  
  722.         NavDisposeReply(&theReply);
  723.         }
  724.     else
  725.         return false;
  726.  
  727.     return result;
  728. }
  729.  
  730.  
  731. // *****************************************************************************
  732. // *
  733. // *    DoSaveAsDocumentOldWay()
  734. // *
  735. // *****************************************************************************
  736. short DoSaveAsDocumentOldWay(Document* theDocument)
  737. {    
  738.     short                theResult;
  739.     Str255                thePrompt, theName;
  740.     StandardFileReply    theReply;
  741.     OSType                fileTypeToSave;
  742.  
  743.     if (!theDocument)
  744.         return false;
  745.  
  746.     GetIndString((unsigned char*)&thePrompt,rAppStringsID,slSavePromptIndex);
  747.     GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  748.     StandardPutFile((unsigned char*)&thePrompt,(unsigned char*)&theName,&theReply);
  749.  
  750.     if (theDocument->theTE != NULL)    // which document type is it?
  751.         fileTypeToSave = kFileType;
  752.     else
  753.         fileTypeToSave = kFileTypePICT;
  754.  
  755.     if (theReply.sfGood)
  756.         {
  757.         if (!theReply.sfReplacing)
  758.             {
  759.             theResult = FSpCreate(&theReply.sfFile,kFileCreator,fileTypeToSave,theReply.sfScript);
  760.             if (theResult)
  761.                 {
  762.                 SysBeep(5);
  763.                 return false;
  764.                 }
  765.             }
  766.             
  767.         if (theDocument->fRefNum)
  768.             theResult = FSClose(theDocument->fRefNum);
  769.         
  770.         theResult = FSpOpenDF(&theReply.sfFile,fsRdWrPerm,&theDocument->fRefNum);
  771.         if (theResult)
  772.             {
  773.             SysBeep(5);
  774.             return false;
  775.             }
  776.  
  777.         if (theResult = WriteFile(theDocument))
  778.             {
  779.             SysBeep(5);
  780.             return false;
  781.             }
  782.  
  783.         SetWTitle(theDocument->theWindow,(unsigned char*)theReply.sfFile.name);
  784.         theDocument->dirty = false;
  785.         }
  786.     else
  787.         return false;
  788.         
  789.     return true;
  790. }
  791.  
  792.  
  793. // *****************************************************************************
  794. // *
  795. // *    DoSaveDocument()
  796. // *
  797. // *****************************************************************************
  798. short DoSaveDocument(Document* theDocument)
  799. {
  800.     short result = noErr;
  801.     if (theDocument != NULL)
  802.         {
  803.         if (theDocument->fRefNum)
  804.             {
  805.             if (WriteFile(theDocument))
  806.                 {
  807.                 SysBeep(5);
  808.                 return false;
  809.                 }
  810.             else
  811.                 theDocument->dirty = false;
  812.             result = true;
  813.             }
  814.         else
  815.             {
  816.             // need to save file for the first time:
  817.             if (gNavServicesExists)
  818.                 {
  819.                 result = DoSaveAsDocument(theDocument);
  820.                 }
  821.             else
  822.                 result = DoSaveAsDocumentOldWay(theDocument);    
  823.             }
  824.         }
  825.     return result;
  826. }
  827.  
  828.  
  829. // *****************************************************************************
  830. // *
  831. // *    DoRevertDocument()
  832. // *
  833. // *****************************************************************************
  834. void DoRevertDocument(Document* theDocument)
  835. {    
  836.     if (theDocument != NULL)
  837.     if (theDocument->fRefNum)
  838.         {
  839.         OSErr                         theErr = noErr;
  840.         NavEventUPP                    eventUPP = NewNavEventProc(myEventProc);
  841.         NavAskDiscardChangesResult     reply;
  842.         NavDialogOptions            dialogOptions;
  843.  
  844.         GetWTitle(theDocument->theWindow,dialogOptions.savedFileName);
  845.         theErr = NavAskDiscardChanges(    &dialogOptions,
  846.                                         &reply,
  847.                                         eventUPP,
  848.                                         (NavCallBackUserData)&gDocumentList);
  849.         DisposeRoutineDescriptor(eventUPP);
  850.  
  851.         switch (reply)
  852.             {
  853.             case kNavAskDiscardChanges:        
  854.                 if (ReadFile(theDocument))
  855.                     SysBeep(5);
  856.                 break;
  857.  
  858.             case kNavAskDiscardChangesCancel:
  859.                 break;
  860.             }
  861.         }
  862. }
  863.  
  864.  
  865. // *****************************************************************************
  866. // *
  867. // *    DoRevertDocumentTheOldWay()
  868. // *
  869. // *****************************************************************************
  870. void DoRevertDocumentTheOldWay(Document* theDocument)
  871. {    
  872.     Str255 theName;
  873.  
  874.     if (!theDocument)
  875.         return;
  876.  
  877.     if (theDocument->fRefNum)
  878.         {
  879.         GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  880.         ParamText((ConstStr255Param)&theName,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  881.         if (Alert(rRevertID,0L) == 1)
  882.             if (ReadFile(theDocument))
  883.                 SysBeep(5);
  884.         }
  885. }
  886.